<?php

/**
 * Description of TableService
 *
 * @author a.novikov
 */
abstract class Service_Table extends Service_Base {

	private $_tableName;

	private $_itemClassName;

	protected function getTableName() {
		if (!$this->_tableName) {
			$className = get_class($this);

			$filter = new Zend_Filter_Word_CamelCaseToUnderscore();

			$this->_tableName = $filter->filter( substr($className, 0, -7) );
		}
		return $this->_tableName;
	}

	protected function setTableName($value) {
		$this->_tableName = $value;
	}

	protected function getItemClassName() {
		if (!$this->_itemClassName) {
			$this->_itemClassName = substr(get_class($this), 0, -7);
		}
		return $this->_itemClassName;
	}

	protected function setItemClassName($value) {
		$this->_itemClassName = $value;
	}

	/**
	 * @return Zend_Validate_Abstract $validator
	 */
	abstract protected function getValidator();

	/**
	 * @return Db_Peer
	 */
	public function getPeer() {
		return Factory::fromUnderscoreComposite($this->getTableName(), 'Peer');
	}

	protected function getItemClass() {
		return Factory::getObject($this->getItemClassName());
	}

	public function validate(array $data) {
		$validator = $this->getValidator();

		$validator->setData($data);

		if (!$validator->isValid()) {
			$messages = $validator->getMessages();

			$errors = array();
			foreach($messages as $item)	{
				$errors[] = implode("\n", (array)$item);
			}

			$messages = implode("\n", $errors);

			throw new Exception_Public($messages);
		}

		return array_merge($data, $validator->getEscaped());
	}

	/**
	 * @return Object_Base $object
	 */
	public function add(array $data) {
		$data = $this->validate($data);

		$peer = $this->getPeer();

		$row = $peer->createRow($data);

		$newId = $row->save();
		if (!$newId) {
			throw new Exception("Failed to insert data");
		}

		$object = call_user_func(array($this->getItemClassName(), 'fromRow'), $peer->fetchById($newId) );
		$object->updateRelationsAdd();
		return $object;
	}
}
?>
